﻿using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Net;
using System.Net.Cache;
using System.Text;
using System.Web;

namespace HttpPublish
{
    public class TrackFileInfo
    {
        public string Name;
        public UInt64 Size;
        public UInt64 Time;
        public bool IsFolder;
    }

    class RemoteTracker
    {
        private const string UriTemplate = "{0}/pub.tree.php?recur=true&path={1}&password={2}";
        private readonly PublishConfigration _config;
        private Dictionary<string, object> _dictionary;

        public RemoteTracker(PublishConfigration config)
        {
            _config = config;
        }

        public Dictionary<string, TrackFileInfo> GetFiles()
        {
            Get();
            return (Dictionary<string, TrackFileInfo>)_dictionary["list"];
        }

        public object this[string key]
        {
            get { return _dictionary[key]; }
        }

        private void Get()
        {
            var uri = string.Format(UriTemplate, _config.Host, HttpUtility.UrlEncode(_config.Remote), HttpUtility.UrlEncode(_config.Password));

            var json = HttpGet(uri);

            if (!String.IsNullOrEmpty(json))
            {

                var tree = JsonHelper.Deserialize<Dictionary<string, object>>(json);

                if (!tree.ContainsKey("result") || (bool)tree["result"] != true)
                {
                    _dictionary = new Dictionary<string, object>();
                    throw new InvalidDataException("Remote file list returned invalid data");
                }

                var list = new Dictionary<string, TrackFileInfo>();

                foreach (object[] items in (object[])tree["list"])
                {
                    var entry = new TrackFileInfo
                                    {
                                        Name = (string)items[0],
                                        Size = (UInt64)(int)items[1],
                                        Time = (((UInt64)(int)items[2]) * 1000),
                                        IsFolder = (bool)items[3]
                                    };
                    if (!entry.IsFolder)
                        list[entry.Name] = entry;
                }
                tree["list"] = list;

                _dictionary = tree;
            }
            else
            {
                _dictionary = new Dictionary<string, object>();
                throw new InvalidDataException("Remote file list returned invalid data");
            }
        }

        public void Abort()
        {
            if (GetWebRequest != null)
                GetWebRequest.EndGetResponse(null);
            
        }

        private HttpWebRequest GetWebRequest;

        private string HttpGet(string uri)
        {
            GetWebRequest = (HttpWebRequest)WebRequest.Create(uri);
            var result = "";
            GetWebRequest.Method = "GET";
            GetWebRequest.Timeout = _config.Timeout;
            GetWebRequest.AllowAutoRedirect = false;
            GetWebRequest.Credentials = new NetworkCredential(_config.User, _config.Password);
            GetWebRequest.PreAuthenticate = true;
            GetWebRequest.CachePolicy = new HttpRequestCachePolicy(HttpRequestCacheLevel.NoCacheNoStore);

            var response = GetWebRequest.GetResponse();
            var stream = response.GetResponseStream();

            if (stream != null)
            {

                var reader = new StreamReader(stream, Encoding.UTF8);
                result = reader.ReadToEnd();
            }

            response.Close();

            return result;
        }
    }
}
